#include "faceattendence.h"
#include "./ui_faceattendence.h"
#include <QDebug>

faceattendence::faceattendence(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::faceattendence)
{
    ui->setupUi(this);
    cap.open(0);
    // Timer start
    startTimer(100);
    // 根据编译环境加载不同路径的模型文件
#ifdef CMAKE_CROSSCOMPILING
    cascade.load("/home/package/opencv-4.5.2/share/opencv4/haarcascades/haarcascade_frontalface_alt2.xml");
#else
    cascade.load("E:/code/Qtproject/package/opencv452/etc/haarcascades/haarcascade_frontalface_alt2.xml");
#endif

    connect(&socket, &QTcpSocket::connected, this, &faceattendence::end_connect);
    connect(&socket, &QTcpSocket::disconnected, this, &faceattendence::start_connect);
    connect(&socket, &QTcpSocket::readyRead, this, &faceattendence::onSocketReadyRead);

    connect(&timer, &QTimer::timeout, this, &faceattendence::QTimer_start);
    timer.start(5000);
    ui->widget_2->hide();
}

faceattendence::~faceattendence()
{
    delete ui;
}

//处理流程：逐步读取视频流并分解成多帧数据，每一帧数据存储在Mat中
//对于每一帧数据，先将其转换为灰度图像，然后使用级联分类器检测人脸
//如果检测到人脸，就将人脸框出来，并将该帧人脸数据发送到服务器
void faceattendence::timerEvent(QTimerEvent *e)
{
    Mat srcImage;//只会存储一帧数据
    if (cap.grab())
    {
        cap.read(srcImage);//读取一帧数据
    }

    Mat grayImage;
    cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
    std::vector<Rect> faceRects;
    cascade.detectMultiScale(grayImage, faceRects, 1.1, 3, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
    if (faceRects.size() > 0)//这里有可能一张图片检测出多个人脸，这里只会标记第一个
    {
        Rect rect = faceRects.at(0);
        // rectangle(srcImage, rect, Scalar(0, 0, 255));
        // 移动人脸框
        ui->headpicLb->move(rect.x, rect.y);

        // 把Mat数据转化为QbyteArray->jpg
        std::vector<uchar> buffer;
        cv::imencode(".jpg", srcImage, buffer);
        QByteArray byteArray((const char *)buffer.data(), buffer.size());
        // 发送数据到服务器
        quint64 backsize = byteArray.size();
        QByteArray sendData;
        QDataStream stream(&sendData, QIODevice::WriteOnly);
        stream.setVersion(QDataStream::Qt_6_8);
        stream << backsize << byteArray;
        // 发送
        socket.write(sendData);    
    }
    else
    {
        ui->headpicLb->move(100, 60);
    }

    if (srcImage.data == nullptr)
        return;

    cvtColor(srcImage, srcImage, COLOR_BGR2RGB);

    QImage image(srcImage.data, srcImage.cols, srcImage.rows, srcImage.step1(), QImage::Format_RGB888);
    QPixmap mmp = QPixmap::fromImage(image);
    ui->videoLb->setPixmap(mmp);
}

void faceattendence::QTimer_start()
{
    socket.connectToHost("127.0.0.1", 8080);
    qDebug() << "connect to host";
}

void faceattendence::end_connect()
{
    timer.stop();
    qDebug() << "connect successful";
}

void faceattendence::start_connect()
{
    timer.start(5000);
    qDebug() << "connect is duan le";
}

void faceattendence::onSocketReadyRead()
{
    static QByteArray buffer;
    static quint64 expectedSize = 0;
    static bool sizeReceived = false;
    
    buffer.append(socket.readAll());
    
    // 首先接收数据大小
    if (!sizeReceived && buffer.size() >= sizeof(quint64)) {
        QDataStream sizeStream(buffer);
        sizeStream.setVersion(QDataStream::Qt_6_8);
        sizeStream >> expectedSize;
        buffer.remove(0, sizeof(quint64));
        sizeReceived = true;
        qDebug() << "Expected data size:" << expectedSize;
    }
    
    // 检查是否接收到完整数据
    if (sizeReceived && buffer.size() >= expectedSize) {
        QDataStream stream(buffer);
        stream.setVersion(QDataStream::Qt_6_8);
        
        int employeeID;
        QString name, currentTime;
        int attendanceStatus;  // 新增考勤状态字段
        quint32 imageSize;
        
        // 按照协议解析数据：工号、姓名、时间、考勤状态、图像数据大小、图像数据
        stream >> employeeID >> name >> currentTime >> attendanceStatus >> imageSize;
        
        QByteArray imageData(imageSize, 0);
        stream.readRawData(imageData.data(), imageSize);
        
        qDebug() << "Received employee data - ID:" << employeeID << "Name:" << name << "Time:" << currentTime << "Status:" << attendanceStatus << "Image size:" << imageSize;
        
        // 更新UI
        updateEmployeeInfo(employeeID, name, currentTime, imageData, attendanceStatus);
        
        // 重置状态
        buffer.clear();
        expectedSize = 0;
        sizeReceived = false;
    }
}

void faceattendence::updateEmployeeInfo(int employeeID, const QString &name, const QString &currentTime, const QByteArray &imageData, int status)
{
    ui->widget_2->show();

    // 更新工号
    ui->id->setText(QString::number(employeeID));
    
    // 更新姓名
    ui->name->setText(name);
    
    // 更新时间
    ui->time->setText(currentTime);
    
    // 更新考勤状态
    QString statusText = (status == 0) ? "考勤成功" : "已完成考勤";
    // 注意：需要在UI文件中添加名为 'status' 的QLabel控件
    // ui->status->setText(statusText);
    
    // 临时使用现有的label_2来显示状态（如果UI中没有status标签）
    ui->label_2->setText(statusText);
    
    // 更新头像
    if (!imageData.isEmpty()) {
        QPixmap pixmap;
        if (pixmap.loadFromData(imageData)) {
            // 缩放图片以适应headLb的大小
            QPixmap scaledPixmap = pixmap.scaled(ui->headLb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
            ui->headLb->setPixmap(scaledPixmap);
            ui->headLb->setScaledContents(true);
            qDebug() << "Employee photo updated successfully";
        } else {
            qDebug() << "Failed to load employee photo from data";
        }
    } else {
        qDebug() << "No image data received";
    }
    
    qDebug() << "UI updated with employee info - ID:" << employeeID << "Name:" << name << "Time:" << currentTime << "Status:" << statusText;
}
